package com.game.NioSocket;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;



import com.commons.DBPool.DBManager;
import com.game.HandleData.IallHandleData;
import com.game.logger.Niologger;
/**
 * 分发管理 
 * @author chenlei
 *
 */
public class dispatcher implements Runnable {
	
	private Selector selector;
	private  SelectionKey sk;
	private IallHandleData hanle;
	public static int countNum=0;//当前在线人数
	
	/**等待注册的队列**/
	public final static ConcurrentLinkedQueue<Gsocket> connectQueue=new ConcurrentLinkedQueue<Gsocket>();
	
	public void process() throws IOException{
		Gsocket Gchannel=null;
		while(!connectQueue.isEmpty()){
			Gsocket gsocket=connectQueue.poll();
				if(gsocket.isOpen()){
					gsocket.Regiester(selector);//注册
					hanle=new IallHandleData();
					/**
					 * 指定数据源操作对象
					 */
					++countNum;
					Niologger.nioLogger.info("当前连接数："+ countNum);
				}else{
					close();
					Niologger.nioLogger.error("channel is shutdown");
				}
		}
		
				int n=selector.select();//选择一组键，其相应的通道已为 I/O 操作准备就绪----选择操作开始
				if(n>0){
					Iterator<SelectionKey> iter=selector.selectedKeys().iterator();
					while(iter.hasNext()){
						SelectionKey key=(SelectionKey)iter.next();
						iter.remove(); //移除已经选择的键集 	
						
						if(key.isValid()&&key.isReadable()){
							try{
								 Gchannel=(Gsocket) key.attachment();
								 Gchannel.ReadData();
								 if(Gchannel.HandleBuffers.size()>0){hanle.dataHandle(Gchannel);}
							}catch(Exception e){
								e.printStackTrace();
								close();
								Niologger.nioLogger.info("read data errors");
							}
							
						} 
						if(key.isValid()&& key.isWritable()){//键有效
							try{
								Gchannel=(Gsocket) key.attachment();
								if(Gchannel.HaveData()){
									Gchannel.SendData();
								}else{
									Niologger.nioLogger.info("no data to send!!!");
								}
							}catch(Exception e){
								close();
								Niologger.nioLogger.info("send data errors",e);
							}
							
						}
					}
				}
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			selector=Selector.open();
			while(DBManager.isRunning){
				process();
			}
		} catch (IOException e) {
			e.printStackTrace();
			close();
		}
		
	}
	
	public void RegisterChannel(Gsocket socketchannel){
		connectQueue.add(socketchannel);
		this.selector.wakeup();
	}
	/**
	 * 关闭选择器
	 */
	public void close(){
		try {
			for(SelectionKey key:this.selector.keys()){
				Gsocket socket=(Gsocket) key.attachment();
				socket.shutdown(socket);
			}
			selector.close();
			sk.cancel();
		} catch (IOException e) {
		
		}
	}
}
